﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FCA.Dto {
    /// <summary>
    /// Y = attribute = intent (itemset, char)
    /// </summary>
    public class ItemSet {
        #region Properties
        /// <summary>
        /// Y = attribute = intent (itemset, char)
        /// </summary>
        public HashSet<int> Items { get; set; }
        #endregion

        #region Constructors
        public ItemSet() {
            Items = new HashSet<int>();
        }

        public ItemSet(HashSet<int> itemSet)
            : this() {
            Items = itemSet;
        }

        public ItemSet(ItemSet itemSet) : this() {
            foreach (int item in itemSet.Items) {
                Items.Add(item);
            }
        }
        #endregion      

        #region Sort
        /// <summary>
        /// linear-time sorting of the intent
        /// </summary>
        /// <param name="c"></param>
        /// <param name="m">max items</param>
        public static List<ItemSet> Sort(List<ItemSet> list, int m) {
            Dictionary<int, List<ItemSet>> bunches = new Dictionary<int, List<ItemSet>>();
            List<ItemSet> order = new List<ItemSet>();

            for (int i = 0; i < m; i++) {
                bunches.Add(i, new List<ItemSet>());
            }

            foreach (ItemSet context in list) {
                int k = context.Length();
                bunches[k - 1].Add(context);
            }

            foreach (KeyValuePair<int, List<ItemSet>> pair in bunches) {
                foreach (ItemSet item in pair.Value) {
                    order.Add(item);
                }
            }
            return order;
        }

        public static void Sort(List<ItemSet> c) {
            c.Sort(delegate(ItemSet a, ItemSet b) {
                return b.Length() - a.Length();
            });
        }

        #endregion

        public string GetValueString() {            
            return string.Join(",", Items);
        }

        public void Add(int item) {
            Items.Add(item);
        }

        public int Length() {
            return this.Items.Count;
        }

        /// <summary>
        /// true if this.Items contain all in y
        /// </summary>
        /// <param name="yi"></param>
        /// <returns></returns>
        public bool IsSuperSetOf(ItemSet y) {
            return Items.IsSupersetOf(y.Items);
        }

        public bool IsSubSetOf(ItemSet y) {
            return Items.IsSubsetOf(y.Items);
        }

        public bool IsEqual(ItemSet y) {
            return Items.SetEquals(y.Items);            
        }

        /// <summary>
        /// contains element existed in both of this and y
        /// </summary>
        /// <param name="y"></param>
        /// <returns></returns>
        public ItemSet IntersectWith(ItemSet y) {            
            ItemSet res = new ItemSet(y);
            res.Items.IntersectWith(Items);
            return res;
        }
        
        /// <summary>
        /// contains element existed in at least one of this and y (U)
        /// </summary>
        /// <param name="y"></param>
        /// <returns></returns>
        public ItemSet UnionWith(ItemSet y) {
            ItemSet res = new ItemSet(y);
            res.Items.UnionWith(Items);
            return res;
        }


        public bool IsAncestorOf(ItemSet items) {
            return IsSubSetOf(items);
        }

        public bool IsDescendantOf(ItemSet items) {
            return IsSuperSetOf(items);
        }
    }
}
